package com.dragon.pear.modules.trade.common.config;

import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;

@Component
public class ImplementationClassFinder {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired(required = false)
    private RequestMappingHandlerMapping handlerMapping;
    
    private static ImplementationClassFinder instance;
    
    @PostConstruct
    public void init() {
        instance = this;
    }
    
    public static ImplementationClassFinder getInstance() {
        return instance;
    }
    
    /**
     * 找到方法对应的实际实现类
     */
    public Class<?> findImplementationClass(Method method) {
        if (!method.isDefault()) {
            return method.getDeclaringClass();
        }
        
        // 首先尝试通过 HandlerMapping 查找
        if (handlerMapping != null) {
            Class<?> result = findThroughHandlerMapping(method);
            if (result != null) return result;
        }
        
        // 然后通过 ApplicationContext 查找
        if (applicationContext != null) {
            Class<?> result = findThroughApplicationContext(method);
            if (result != null) return result;
        }
        
        return null;
    }
    
    private Class<?> findThroughHandlerMapping(Method method) {
        try {
            Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
            for (HandlerMethod handlerMethod : handlerMethods.values()) {
                if (isSameMethod(handlerMethod.getMethod(), method)) {
                    return handlerMethod.getBeanType();
                }
            }
        } catch (Exception e) {
            // 忽略异常
        }
        return null;
    }
    
    private Class<?> findThroughApplicationContext(Method method) {
        String[] beanNames = applicationContext.getBeanNamesForType(method.getDeclaringClass());
        for (String beanName : beanNames) {
            Object bean = applicationContext.getBean(beanName);
            try {
                Method beanMethod = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
                if (beanMethod.getDeclaringClass().isInterface()) {
                    return bean.getClass();
                }
            } catch (NoSuchMethodException e) {
                // 忽略
            }
        }
        return null;
    }
    
    private boolean isSameMethod(Method m1, Method m2) {
        return m1.getName().equals(m2.getName()) &&
               Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
    }
}